﻿using System;
using System.Collections.Generic;
using System.Data.Entity; // needed for lambda includes
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;

namespace TheCup.ApiControllers
{
    public class EventController : ApiController
    {
        TheCupContext ctx = new TheCupContext();
        PlayerController pc = new PlayerController();

        /// <summary>
        /// Gets all future Events
        /// </summary>
        /// <returns>List</returns>
        public IEnumerable<Event> Get()
        {
            return (from ev in ctx.Events.Include(j => j.Joins) //.Include(c => c.Category)
                    select ev).ToList<Event>();
        }

        public IEnumerable<Event> GetRecentEvents()
        {
            // create span for showing recent events
            DateTime today = DateTime.UtcNow.Date;
            DateTime cutDate = today.AddDays(-30);
            
            return (from ev in ctx.Events.Include(j => j.Joins) //.Include(c => c.Category)
                    where ev.StartDate > cutDate.Date && ev.StartDate <= today
                    select ev).OrderByDescending(dd => dd.StartDate).ToList<Event>();
        }

        [Authorize]
        public Event Get(int Id)
        {
            return (from item in ctx.Events.Include(p => p.Organizer).Include(j => j.Joins).Include(b => b.Joins.Select(p => p.Player)).Include(c => c.Type).Include(c2 => c2.Course)
                    where item.Id == Id
                    select item).First();
        }
        
        /// <summary>
        /// Cleans up expired events by setting datedeleted
        /// </summary>
        [Route("api/event/cleanup")]
        public void GetCleanup()
        {
            List<Event> e = (from ev in ctx.Events
                             where ev.StartDate < DateTime.Today && ev.DateDeleted == null
                             select ev).ToList();
            e.ForEach(ev => ev.Expire());
            ctx.SaveChanges();
        }

        public void NotifyAttendeesOnEventUpdate(Event e)
        {
            string subject = string.Format("'{0}' opdateret", e.Name);
            string body = e.ContentAsHtml;
            body += string.Format("<p>Læs mere om eventet på <a href='http://www.thecup.dk/Event/Details/{0}'>The Cup</a></p>", e.Id);

            TheCupMailNotifier mailer = new TheCupMailNotifier(subject, body);
            foreach (var join in e.Joins)
            {
                mailer.AddRecipient(join.Player);
            }

            mailer.Send();
        }

        public void NotifyAttendeesOnEventJoin(Event evnt, Player player)
        {
            string subject = string.Format("{0} er tilmeldt '{1}'", player.DisplayName, evnt.Name);
            string body = evnt.ContentAsHtml;
            body += string.Format("<p>Læs mere om eventet på <a href='http://www.thecup.dk/Event/Details/{0}'>The Cup</a></p>", evnt.Id);
                        
            TheCupMailNotifier mailer = new TheCupMailNotifier(subject, body.ToString());
            var joins = ctx.EventJoins.Include(p => p.Player).Where(e => e.EventId == evnt.Id).ToList();

            foreach (var join in joins)
            {
                mailer.AddRecipient(join.Player);
            }

            mailer.Send();
        }

        public void NotifyAttendeesOnEventLeave(Event e, Player p)
        {
            throw new NotImplementedException();
        }

        public void NotifyAttendeesOnEventCreate(Event e)
        {
            string subject = "Nyt event: " + e.Name;
            StringBuilder body = new StringBuilder();
            body.Append("<h4>");
            body.AppendFormat("Den. {0}", e.StartDate.ToString("D"));
            body.Append("</h4>");
            body.AppendLine(e.ContentAsHtml);
            body.AppendFormat("<p>Læs mere om eventet på <a href='http://www.thecup.dk/Event/Details/{0}'>The Cup</a></p>", e.Id);
            
            ApiControllers.PlayerController pc = new ApiControllers.PlayerController();
            List<Player> players = pc.Get().ToList<Player>();

            TheCupMailNotifier mailer = new TheCupMailNotifier(subject, body.ToString());

            foreach (Player p in players.Where(pl => pl.IsActive && pl.SendEventMails == true))
            {
                mailer.AddRecipient(p);
            }

            mailer.Send();
        }

        [HttpPost]
        public void JoinEvent(Event ev, Player pl)
        {
            if (this.PlayerJoinedEvent(ev.Id, pl.Id))
            {
                // nothing to do; player already joined for some freakin' reason
            }
            else
            {
                EventJoin ej = new EventJoin();
                ej.uuid = Guid.NewGuid();
                ej.DateJoined = DateTime.UtcNow;
                ej.LegacyEventId = ev.uuid;
                ej.LegacyPlayerId = pl.uuid;
                ej.PlayerId = pl.Id;
                ej.EventId = ev.Id;
                ctx.EventJoins.Add(ej);
                ctx.SaveChanges();

                // the event is not refreshed so the player joining will not get an email
                NotifyAttendeesOnEventJoin(ev, pl);
            }
        }

        public bool PlayerJoinedEvent(int eventId, int playerId)
        {
            return ctx.EventJoins.Where(j => j.PlayerId == playerId & j.EventId == eventId).Count() > 0;
        }

        [Authorize]
        public void Leave(int eventId)
        {
            Event e = Get(eventId);
            Player pl = new PlayerController().GetLoggedInPlayer();
            EventJoin ej = ctx.EventJoins.First(join => join.PlayerId == pl.Id && join.EventId == e.Id);
            ctx.EventJoins.Remove(ej);
            ctx.SaveChanges();
        }

        // POST api/<controller>
        [Authorize]
        [HttpPost]
        public void Post([FromBody] Event e)
        {
            // need this for comments
            e.uuid = Guid.NewGuid();
            e.DateDeleted = null;
            e.WhenCreated = DateTime.Now;
            e.ApplyRules();

            Player currentUser = pc.GetLoggedInPlayer();
            e.PlayerId = currentUser.Id;
            e.LegacyOwnerUuid = currentUser.uuid;

            ctx.Events.Add(e);
            ctx.SaveChanges();

            NotifyAttendeesOnEventCreate(e);

            // automagically add the organizer
            JoinEvent(e, currentUser);
        }

        // PUT api/<controller>/5
        [Authorize]
        [HttpPut]
        public void Put(int id, [FromBody]Event e)
        {
            if (ModelState.IsValid)
            {
                Event ev = this.Get(id);
                ctx.Entry(ev).CurrentValues.SetValues(e);
                //ev.CourseId = e.CourseId;
                ev.ApplyRules();

                ctx.SaveChanges();

                NotifyAttendeesOnEventUpdate(ev);
            }
        }

        // DELETE api/<controller>/5
        [Authorize]
        [HttpDelete]
        public void Delete(int id)
        {
            Event e = this.Get(id);

            e.Expire();

            ctx.SaveChanges();
        }
    }

}